home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / AOSVS.C < prev    next >
C/C++ Source or Header  |  1993-03-02  |  57KB  |  1,933 lines

  1. /*
  2.  * aosvs.c  -  AOS/VS & MV/UX version of the termio.c module
  3.  *
  4.  * The functions in this module deal with the O/S in reading/writing
  5.  * characters from/to the screen.  We also deal with various wiedness things
  6.  * in dealing with the AOS/VS file system such as ACL's and elementsizes.
  7.  * This has been written primarily for AOS/VS but should work for MV/UX as
  8.  * well.  No promises though.
  9.  *
  10.  * AOS/VS and MV/UX are products of Data General Corporation, Westboro MA.
  11.  *
  12.  * Authors:
  13.  *          Daniel Lawrence --- doing MicroEmacs... stuff copied into here...
  14.  *          Douglas Rady ------ most of the rest of the stuff here
  15.  * Credits:
  16.  *          Michael Meissner -- beating Doug over the head with advice and info.
  17.  *                              on AOS/VS "C" compiler.     THANK YOU!!!!!!!!!!
  18.  *          Bill Benedetto
  19.  *          & friends      ---- beta victims, bug finders/fixers
  20.  *          GNU --------------- inspiration, software tools, clean readable BSD
  21.  *                              and USG code examples and interesting comments.
  22.  *
  23.  * Definition: uka = Unixly Known As
  24.  *
  25.  * Revision/Hack History
  26.  *  MicroEMACS v3.<9p,10> AOS/VS History
  27.  *  
  28.  *  3.09.16.00 - 3.09.16.09         ??-???-??           dcr
  29.  *      Before written history.  Suffice to say that .00 - .04 was just the
  30.  *      AOS/VS port from 3.8z, 3.9e, 3.9i and 3.9n with major cleaning up and
  31.  *      rewriting of the AOS/VS stuff.  Sub-revisions 3.09.16.05 - 3.09.16.09
  32.  *      being optimizations and various fixes.
  33.  *      Yawn...
  34.  *
  35.  *  3.09.16.10                      25-Aug-88           dcr
  36.  *      Changed  do_system_end()  in  aosvs.c  to check for execution of a 
  37.  *    macro as basis for not executing an  mlreply("Continue")  call.
  38.  *      Also fixed  stime()  in  aosvs.c  so it just plain worked.
  39.  *      #$&^@*&(+$#!!!!
  40.  *      Also added  REPLYNL  in  estruct.h  and made use of CR or NL in the
  41.  *      mlreply()  routine in  input.c  compile time conditional.
  42.  *
  43.  *  3.09.16.11                      13-Sep-88           dcr
  44.  *      Start of written hisory.  This is a momentous event in the course of
  45.  *      AOS/VS MicroEMACS history: doug writes some change doc.!!! Yeah!!!
  46.  *      Changed several functions to force the  $builtin  version as a trade of
  47.  *      more code size for more speed (usually defaulted to $builtin anyway...).
  48.  *
  49.  *  3.09.16.12                      14-Sep-88           dcr
  50.  *      Recompiled with revision 4.00 of AOS/VS C.  A miracle...
  51.  *
  52.  *  3.09.16.13                      12-Oct-88           dcr
  53.  *      Changed to have the temporary file for pipecmd() be created in a system
  54.  *      wide temporary file directory known as :TMP, uka /tmp.  You paranoids
  55.  *      can create :TMP as a CPD with max. size of 2048 blocks and an ACL of
  56.  *      +,WE and you should be able to relax a nibble.
  57.  *      Creates temp. file with ACL of  username,OWAR
  58.  *
  59.  *  3.09.16.14                      13-Oct-88           dcr
  60.  *      Put in MCA's hack to reduce memory consumption when VIEWing a file.
  61.  *      Modified  lalloc()  in line.c  Test case of paru.h saved 27 2Kb pages.
  62.  *
  63.  *  3.10.00.00                      09-Nov-88           dcr
  64.  *      Begin code porting for 3.10 BETA.
  65.  *
  66.  *  3.10.00.01                      20-Dec-88           dcr
  67.  *      Implemented multi-language messages in  aosvs.c  per 3.10 BETA.
  68.  *
  69.  *  3.10.00.02                      26-Dec-88           dcr
  70.  *      Tracked down some un-documented runtime optimizations and got
  71.  *      a working version. Also resolved timeset() references.
  72.  *
  73.  *  3.10.00.03                      17-Jan-89           dcr
  74.  *      Cleaned up for shipping to Dan.  Put in some missing code for input.c
  75.  *
  76.  *  3.10.00.04                      17-Jan-89           dcr
  77.  *      Put in some optimizations regarding TTflush() and ostring() in the
  78.  *      bind.c, input.c and aosvs.c files.  This freed 2Kb... but not for long.
  79.  *
  80.  *  3.10.00.05                      17-Jan-89           dcr
  81.  *      Some memory optimization in  exec.c  and  input.c for small regain.
  82.  *
  83.  *  3.10.00.06 - 3.10.00.27     02-Mar-89 - 10-Mar-89   dcr
  84.  *      Various changes. Cleaned up the AOS/VS changes in other modules so 
  85.  *      we actually work right.  Added conditionals for using either BSD or
  86.  *      USG console i/o (BSD doesn't seem to work).  Reclaimed about 4Kb of 
  87.  *      memory in various places and made some of these optimizations compile
  88.  *      time conditional. We are still using .890+ ms to start up intead of the
  89.  *      .520+ ms that we took with 3.9p. Not much hope there... but...
  90.  *      Various tweaks here and there.  Added the skip of nulls when reading in
  91.  *      a file (most unpleasant results if we don't).  Lost some memory to the
  92.  *      USG console i/o stuff.  Threw out the BSD console i/o stuff, sigh....
  93.  *
  94.  *  3.10.00.28                      10-Mar-89           dcr
  95.  *      Stuck in the  aosvs$unix_to_aosvs_path()  routine to replace the code
  96.  *      in resolve_pathname().  The new routine does a fairly complete job of
  97.  *      converting Unix(tm) pathnames to AOS/VS format. It also handles the 
  98.  *      Ms-Dog '\' path seperator.
  99.  *  
  100.  *  3.10.00.29                      16-Mar-89           dcr
  101.  *      Changed pathname expansion to be invisible to user.  Required changes
  102.  *      to  fileio.c  to #if AOSVS  replace the fopen() calls with our xxfopen()
  103.  *      call which does the pathname expansion.  Allowed removal of all the
  104.  *      related to the EXPPATH define.  Also changed several routines here.
  105.  *      Allows user to reference buffer & file names w/o "unexpanding" the 
  106.  *      orginal pathname.
  107.  *      Diff'd & sent to Dan.
  108.  *
  109.  */
  110.  
  111. #nolist
  112. #include        <stdio.h>           /* get the usual */
  113. #list
  114. #include        "estruct.h"         /* get the MicroEMACS stuff */
  115.  
  116. #ifdef  AOSVS | MV_UX               /* should this be done? */
  117.  
  118. #define dashertermdef   1           /* might not be used any more */
  119.  
  120. #nolist
  121. #include        "edef.h"            /* get the MicroEMACS extern's */
  122. #include        "elang.h"
  123. #list
  124.  
  125. /* There is no kitchen sink in C so we can't include it. Maybe in C++... */
  126. #nolist
  127. #include    <paru.h>                /* AOS/VS system mnemonics */
  128. #include    <sysid.h>               /* AOS/VS system call mnemonics */
  129. #include    <packets/characteristics.h> /* sys call packet for terminal char.*/
  130. #include    <packets/create.h>      /* sys call packet to create files */
  131. #include    <packets/filestatus.h>  /* sys call packet to get file info */
  132. #include    <packets/misc.h>        /* misc. sys call packets (?SYSPRV) */
  133.  
  134. /* And now... the Unix(tm) stuff... */
  135. #include    <fcntl.h>               /* terminal file control stuff */
  136. #include    <signal.h>              /* the signals... */
  137. #include    <termio.h>              /* more terminal control stuff */
  138. #list
  139.  
  140. /*
  141.     Variables!!!   Functions!!!  Externals!!!!
  142. */
  143. struct  termio  old_in_termio;  /* original stdin terminal characteristics */
  144. struct  termio  new_in_termio;  /* stdin characteristics to use inside */
  145.  
  146. int kbdpoll;                    /* type ahead polling flag      */
  147. int kbdflgs;                    /* saved keyboard fd flags      */
  148. int kbdqp;                      /* there is a char in kbdq      */
  149. char kbdq;                      /* char we've already read      */
  150.  
  151. /*
  152.     some D.G. supplied AOS/VS & MV/UX specific functions
  153.  
  154.     _toaos_fid() - changes UNIX(tm)  pathname to AOS/VS pathname (Thank you!)
  155.     traceback() - calls the ?SNAP LANG_RT routine for error traceback
  156. */    
  157. /*extern int  _toaos_fid(char*, char* );*/
  158. extern VOID traceback(int );
  159.  
  160. /*
  161.     This is how we make an MV/Eclipse accumulator in C with almost all options.
  162. */
  163. union accumulator {                 /* dearly beloved, we are gathered here...*/
  164.     unsigned long * ptr;            /* pointer to unsigned long (generic) */
  165.     char *          cptr;           /* pointer to char */
  166.     unsigned int  * pint;           /* pointer to unsigned int */
  167.     unsigned short *psht;           /* pointer to short */
  168.     unsigned long   ulng;           /* unsigned long */
  169.     signed long     lng;            /* signed long */
  170.     unsigned int    uin;            /* unsigned int */
  171.     signed int      in;             /* signed int */
  172.     unsigned short usht;            /* unsigned short */
  173.     unsigned char   chr;            /* a char, unsigned of course!!! */
  174. } ac0, ac1, ac2;                    /* our bountiful accumulators, sigh... */
  175.     
  176.  
  177. P_CREATE    create_pkt;             /* file create system call packet */
  178. P_FSTAT     fstat_pkt;              /* file status system call packet */
  179. char acl_buf[ $MXACL ];             /* ACL buffer, gotta protect things... */
  180. char *crt_eol="\013";               /* Dasher D2xx commands */
  181. char *crt_eop="\014";               /* Dasher D2xx commands */
  182. int dimsts, revsts;
  183. int su_mode;                        /* Superuser mode flag */
  184. #define TLINE_LEN   512
  185. char tline[TLINE_LEN];                /* command line for cli/shell/program calls */
  186.  
  187. extern VOID do_system();        /* calls the cli/shell/program */
  188. extern VOID do_system_end();    /* cleans up after cli/shell/program calls */
  189. extern VOID init_tline();       /* inits the command line for cli/shell... */
  190. extern VOID ttputs();
  191. extern VOID in_init();
  192. extern FILE *ffp;               /* file stream pointer used in fileio.c */
  193. extern int vttidy();            /* MicroEMACS routine to tidy up the screen */
  194.  
  195. extern int              aosvs$expand_pathname();
  196. extern void             aosvs$unix_to_aosvs_path();
  197. #endif
  198.  
  199. FILE *STDIN, *STDOUT;           /* Needed since the array of files went away.*/
  200.                                 /* Of course, if _iob changes, we'll have to */
  201.                 /* bend over since we use  ->_file  in _iob. */
  202.  
  203. static int mexist;    /* is the mouse driver installed? */
  204. static int nbuttons;    /* number of buttons on the mouse */
  205. static int oldbut;    /* Previous state of mouse buttons */
  206.  
  207. /*------------------------------------------------------------------------------
  208.  *  resolve_full_pathname(char*, char*) - resolves a filename or pathname to
  209.  *  full AOS/VS pathname via the ?GRNAME system call.  If the file does not
  210.  *  exsist then the current working directory is assumed by  AOS/VS.
  211.  *
  212.  *  Returns  FIOSUC  if  from_path  is found or  FIOFNF  if it isn't found.
  213.  */
  214. int resolve_full_pathname(from_path, to_path)
  215.  
  216. char *from_path, *to_path;      /* resolve "from" pathname "to" pathname */
  217. {
  218.     if (aosvs$expand_pathname(from_path, to_path))
  219.         return(FIOFNF);
  220.  
  221.     return(FIOSUC);
  222. }
  223.  
  224. /*
  225.  *  ffwopen() - AOS/VS specific version of the ffwopen() routine found in the
  226.  *  fileio.c source.  This version will attempt to recreate the edit file
  227.  *  (if it exists) with the existing edit file ACL, elementsize, filetype and
  228.  *  recordsize parameters as determined via a ?FSTAT filestatus system call.
  229.  *
  230.  *  Returns  FIOSUC  if file is opened or  FIOERR  if not opened.
  231.  *
  232.  *    DOUG, we need to make the mode param work here, or ignore it....
  233.  */
  234. int ffwopen(bfilnam, mode, sfilnam)
  235.  
  236. char *bfilnam;    /* buffer file name */
  237. char *mode;      /* mode for file open (w = write, a = append) */
  238. char *sfilnam;    /* save file name or NULL */
  239. {
  240.     char bfnam[NFILEN], sfnam[NFILEN];
  241.     char *tptr;
  242.  
  243.     /* some initializations */
  244.     zero((char *) &create_pkt, sizeof(create_pkt));
  245.     zero((char *) &fstat_pkt, sizeof(fstat_pkt));
  246.     zero(acl_buf, $MXACL);
  247.  
  248.     strcpy(bfnam, bfilnam);
  249.     if (sfilnam) {
  250.         strcpy(sfnam, sfilnam);
  251.     resolve_full_pathname(sfnam, sfnam);
  252.         tptr = sfnam;
  253.     } else {
  254.         tptr = bfnam;    
  255.     }
  256.     
  257.     create_pkt.ctim = -1L;      /* take default file creation time */
  258.     create_pkt.cacp = -1L;      /* take default file creation acl */
  259.     create_pkt.cdel = -1L;      /* take default file creation elementsize */
  260.     create_pkt.cmil = -1L;      /* take default file creation max. index levels */
  261.     fstat_pkt.stim = -1L;
  262.     fstat_pkt.sacp = -1L;
  263.  
  264.     /* attempt to get full AOS/VS pathname of the file */
  265.     if  ((resolve_full_pathname(bfnam, bfnam)) == FIOFNF) { /* edit file found? */
  266.         /* bfnam not found, create one with default specs. */
  267.         create_pkt.cftyp_format = $ORDS;    /* data sensitive record type */
  268.         create_pkt.cftyp_entry  = $FTXT;    /* text file type */
  269.         ac2.ptr = &create_pkt;
  270.         ac1.lng = 0L;
  271.  
  272.         ac0.cptr = tptr;
  273.  
  274.         /* have AOS/VS attempt to create the file */
  275.         if  (sys($CREATE, &ac0, &ac1, &ac2))
  276.             goto fubar;
  277.  
  278.     } else {    /* bfnam found, get filestatus info. for recreation of bfnam */ 
  279.         ac2.ptr = &fstat_pkt;
  280.         ac1.lng = 0L;
  281.         ac0.cptr = bfnam;
  282.         /* have AOS/VS attempt to get the file information for us */
  283.         if  (sys($FSTAT, &ac0, &ac1, &ac2))
  284.             goto fubar;
  285.  
  286.         /*
  287.             Get ACL of bfnam.  If we can't get that then we get the
  288.             default ACL and use that.
  289.         */
  290.         ac0.cptr = bfnam;
  291.         ac1.cptr = acl_buf;
  292.         ac2.lng = 0L;
  293.         if  (sys($GACL, &ac0, &ac1, &ac2)) {    /* try to get the file ACL */
  294.             /* can't get ACL of file, get default ACL */
  295.             ac0.lng = 0L;
  296.             ac2.lng = 0L;
  297.             ac1.cptr = acl_buf;
  298.             sys($DACL, &ac0, &ac1, &ac2); /* try to get user default ACL */
  299.         }
  300.  
  301.         /*
  302.             Delete  sfnam  file.  We don't care about any errors on this.
  303.         */
  304.         ac0.cptr = tptr;
  305.         ac1.lng = 0L;
  306.         ac2.lng = 0L;
  307.         sys($DELETE, &ac0, &ac1, &ac2);   /* delete it */
  308.     
  309.         /*
  310.             Set up the packet for the file create system call
  311.         */
  312.         create_pkt.cftyp_format = fstat_pkt.styp_format;    /* file format  */
  313.         create_pkt.cftyp_entry  = fstat_pkt.styp_type;      /* file type    */
  314.         create_pkt.ccps = fstat_pkt.scps;   /* recordsize, if any */
  315.         create_pkt.cacp = acl_buf;          /* acl buffer ptr   */
  316.         create_pkt.cdeh = fstat_pkt.sdeh;   /* element size     */
  317.         create_pkt.cmil = fstat_pkt.smil;   /* max. index level */
  318.  
  319.         /*
  320.             Make system call to create a file with supplied specs.
  321.         */
  322.         ac2.ptr  = &create_pkt;
  323.         ac0.cptr = tptr;
  324.  
  325.         ac1.lng = 0L;
  326.         if  (sys($CREATE, &ac0, &ac1, &ac2))    /* attempt file create */
  327.             goto fubar;
  328.     }
  329.  
  330.     if  ((ffp = fopen(tptr, "a")) == NULL)
  331.             goto fubar;
  332.  
  333. #if     ISADIR
  334.     if  (isadirectory(ffp)) {   /* check to see if file is a directory */
  335.         mlwrite(TEXT216);       /* bitch... */
  336.     ffclose(ffp);           /* yes, close it and get out!!! */
  337.         return(FIOERR);         /* actual checking code in O/S modules */
  338.     }
  339. #endif
  340.  
  341.     return(FIOSUC);
  342.  
  343.     /*
  344.         Common error exit for all  ffwopen()  errors
  345.     */
  346. fubar:
  347.     mlwrite(TEXT155);
  348. /*    mlwrite("Cannot open file for writing");*/
  349.     return(FIOERR);
  350. }
  351.  
  352. /*
  353.  *  unlink() - delete a file - called from  writeout()  in  file.c
  354.  *
  355.  *  This routine replaces the DG supplied  unlink()  since we don't use the
  356.  *  link() unlink() combination to rename files.  Saves some memory.
  357.  *
  358.  */
  359. int unlink(del_fnam)
  360.  
  361. char *del_fnam;        /* name of file to delete */
  362. {
  363.     char dtmp[NFILEN];
  364.  
  365.     strcpy(dtmp, del_fnam);
  366.     resolve_full_pathname(dtmp, dtmp);
  367.     ac0.cptr = dtmp;
  368.     ac1.lng = 0L;
  369.     ac2.lng = 0L;
  370.     if (sys($DELETE, &ac0, &ac1, &ac2))    /* attempt to delete it */
  371.         return(-1);                           /* normal error return */
  372.     return(0);                                /* normal okay return */
  373. }
  374.  
  375. /*
  376.  *  rename() - rename a file - called from  writeout()  in  file.c
  377.  */
  378. int rename(from_nam, to_nam)
  379.  
  380. char *from_nam;     /* rename from name */
  381. char *to_nam;       /* rename to name */
  382. {
  383.     char ftmp[NFILEN], ttmp[NFILEN];
  384.  
  385.     /*
  386.         First we convert Unix(tm) or Ms-dog paths to Aos/Vs paths.
  387.         Second we strip the actual filename from the "to" path by going to the
  388.     end of the string and working our way backward until we find a pathname
  389.     seperator which under AOS/VS is a colon (:).
  390.     */
  391.     strcpy(ftmp, from_nam);
  392.     strcpy(ttmp, to_nam);
  393.     resolve_full_pathname(ftmp, ftmp);
  394.     resolve_full_pathname(ttmp, ttmp);
  395.  
  396.     ac1.cptr = ttmp + (sizeof(char) * strlen(ttmp));
  397.     while ((ac1.cptr >= ttmp) && (*ac1.cptr != ':') && (*ac1.cptr != '='))
  398.         --ac1.cptr;
  399.  
  400.     ++ac1.cptr;     /* move pointer from seperator to 1st char in filename */
  401.     ac0.cptr = ftmp;
  402.     ac2.lng = 0L;
  403.     if  (sys($RENAME, &ac0, &ac1, &ac2))    /* attempt the rename */
  404.         return(-1);   /* oops!!! */
  405.     return(0);        /* okay... */
  406. }
  407.  
  408. /*
  409.  * This function gets called just before we go back home to the command
  410.  * interpreter.
  411.  */
  412. VOID ttclose()
  413. {
  414.     fflush(stdout);
  415.     fflush(stdin);
  416.     ioctl(STDIN->_file, TCSETA, &old_in_termio);     /* restore terminal settings */
  417.     fcntl(STDIN->_file, F_SETFL, kbdflgs);
  418. }
  419.  
  420. /*
  421.  * Write a character to the display.
  422.  */
  423. #if TTPUTC == 0
  424. VOID ttputc(c)
  425. {
  426.     putc(c, stdout);
  427. }
  428. #endif
  429.  
  430. /*
  431.  * Flush terminal buffer. Does real work where the terminal output is buffered
  432.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  433.  */
  434. #if TTFLUSH == 0
  435. VOID ttflush()
  436. {
  437.     fflush(stdout);
  438. }
  439. #endif
  440.  
  441. unsigned int extcode(c)
  442.  
  443. unsigned int c;
  444.  
  445. {
  446.     if ((c == 1 || c == 8 || c == 17 || c == 23) || (c >= 24 && c <=26)
  447.         || (c >= 32 && c <= 110) || (c >= 112 && c <= 126))   /* 111 is mouse */
  448.         return((c & 255) | SPEC);
  449.  
  450.     return(c & 255);
  451. }
  452.  
  453. /*    input buffers and pointers    */
  454.  
  455. #define    IBUFSIZE    64    /* this must be a power of 2 */
  456.  
  457. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  458. int in_next = 0;        /* pos to retrieve next input character */
  459. int in_last = 0;        /* pos to place most recent input character */
  460.  
  461. VOID in_init()  /* initialize the input buffer */
  462.  
  463. {
  464.     in_next = in_last = 0;
  465. }
  466.  
  467. int in_check()    /* is the input buffer non-empty? */
  468.  
  469. {
  470.     if (in_next == in_last)
  471.         return(FALSE);
  472.     else
  473.         return(TRUE);
  474. }
  475.  
  476. VOID in_put(event)
  477.  
  478. int event;    /* event to enter into the input buffer */
  479.  
  480. {
  481.     in_buf[in_last++] = event;
  482.     in_last &= (IBUFSIZE - 1);
  483. }
  484.  
  485. int in_get()    /* get an event from the input buffer */
  486.  
  487. {
  488.     register int event;    /* event to return */
  489.  
  490.     event = in_buf[in_next++];
  491.     in_next &= (IBUFSIZE - 1);
  492.     return(event);
  493. }
  494. #if    MOUSE
  495. int checkmouse()
  496.  
  497. {
  498.     register int k;        /* current bit/button of mouse */
  499.     register int event;    /* encoded mouse event */
  500.     int newbut;        /* new state of the mouse buttons */
  501.     int mousecol;        /* current mouse column */
  502.     int mouserow;        /* current mouse row */
  503.     int sstate;        /* current shift key status */
  504.  
  505.     /* check to see if any mouse buttons are different */
  506. /*    rg.x.ax = 3;*/    /* Get button status and mouse position */
  507. /*    int86(0x33, &rg, &rg);*/
  508. /*    newbut   = rg.x.bx;*/
  509. /*    mousecol = rg.x.cx >> 3;*/
  510.     mouserow = rg.x.dx >> 3;
  511.  
  512.     /* get the shift key status as well */
  513.     sstate = 0;
  514. /*    rg.h.ah = 2;*/    /* return current shift status */
  515. /*    int86(0x16, &rg, &rg);*/
  516. /*    sstate = rg.h.al;*/
  517.  
  518.     for (k=1; k != (1 << nbuttons); k = k<<1) {
  519.         /* For each button on the mouse */
  520.         if ((oldbut&k) != (newbut&k)) {
  521.             /* This button changed, generate an event */
  522.             in_put(0);
  523.             in_put(MOUS >> 8);
  524.             in_put(mousecol);
  525.             in_put(mouserow);
  526.             event = ((newbut&k) ? 0 : 1);    /* up or down? */
  527.             if (k == 2)            /* center button? */
  528.                 event += 4;
  529.             if (k == 4)            /* right button? */
  530.                 event += 2;
  531.             if (sstate & 3)            /* shifted */
  532.                 event += 'A';
  533.             else if (sstate & 4)        /* controled? */
  534.                 event += 1;
  535.             else
  536.                 event += 'a';        /* plain */
  537.             in_put(event);
  538.             oldbut = newbut;
  539.             return(TRUE);
  540.         }
  541.     }
  542.     return(FALSE);
  543. }
  544. #endif
  545.  
  546. int doschar()
  547.  
  548. {
  549. /* USG - SysV console i/o - From  "C Users Journal", April 1989, Vol. 7, # 9 */
  550.     if(kbdqp)               /* any typeahead known? */
  551.         kbdqp = FALSE;      /* yes, clear flag & return typeahead char */
  552.     else {                  /* no typeahead. */
  553.         if (fcntl(STDIN->_file, F_SETFL, kbdflgs) < 0 && kbdpoll)
  554.             return(FALSE);
  555.         kbdpoll = FALSE;
  556.         read(STDIN->_file, &kbdq, 1);   /* wait and get a char */
  557.     }
  558.     if (kbdq == '\036') {   /* D.G. Dasher CRT function key lead-in? */
  559.         in_put(SPEC >> 8);  /* ??? stash in the keyboard buffer stuff ??? */
  560.         return(0);
  561.     }
  562.     return (kbdq & 255);
  563. }
  564.  
  565. /*
  566.  * Read a character from the terminal, performing no editing and doing no echo
  567.  * at all.
  568.  */
  569. int ttgetc()
  570. {
  571.         /* return any keystrokes waiting in the
  572.         type ahead buffer */
  573. ttc:    if (in_check())
  574.         return(in_get());
  575.  
  576.     if (typahead())
  577.         return(doschar());
  578.  
  579.     /* with no mouse, this is a simple get char routine */
  580.     if (mexist == FALSE || mouseflag == FALSE)
  581.             return(doschar());
  582.  
  583. #if    MOUSE
  584.     /* turn the mouse cursor on */
  585. /*    rg.x.ax = 1;*/    /* Show Cursor */
  586. /*    int86(0x33, &rg, &rg);*/
  587.     /* loop waiting for something to happen */
  588.     while (TRUE) {
  589.         if (typahead())
  590.             break;
  591.         if (checkmouse())
  592.             break;
  593.     }
  594.  
  595.     /* turn the mouse cursor back off */
  596. /*    rg.x.ax = 2;*/    /* Hide Cursor */
  597. /*    int86(0x33, &rg, &rg);*/
  598.  
  599.         goto ttc:
  600. #endif  /* MOUSE */
  601. }
  602.  
  603. #if     TYPEAH
  604. /* typahead:    Check to see if any characters are already in the
  605.                 keyboard buffer.  Hurray for kludges!!!
  606. */
  607. int typahead()
  608. {
  609. /* USG - SysV console i/o - From  "C Users Journal", April 1989, Vol. 7, # 9 */
  610.     if (!kbdqp) {
  611.         if (fcntl(STDIN->_file, F_SETFL, (kbdflgs | O_NDELAY)) < 0 && kbdpoll)
  612.             return(FALSE);
  613.         kbdpoll = TRUE;
  614.         kbdqp = (1 == read(STDIN->_file, &kbdq, 1));
  615.     }
  616.     return(kbdqp);
  617. }
  618.  
  619. #endif  /* TYPEAH */
  620.  
  621. /*      Spawn:  various DOS access commands
  622.                 for MicroEMACS ver 3.9e
  623. */
  624.  
  625.  
  626. /*
  627.  * Create a subjob with a copy of the command intrepreter in it. When the
  628.  * command interpreter exits, mark the screen as garbage so that you do a full
  629.  * repaint. Bound to "^X C".
  630.  */
  631. int spawncli(f, n)
  632. {
  633.     register char *cp;
  634.  
  635.     /* don't allow this command if restricted */
  636.     if (restflag)
  637.         return(resterr());
  638.  
  639. #if     MV_UX
  640.     TTflush();
  641.     TTclose();                              /* stty to old settings */
  642.     if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  643.         system(cp);
  644.     else
  645.         system("exec /bin/sh");
  646. #endif
  647.  
  648. #if     AOSVS
  649.     init_tline();
  650.     strcat(tline,"CHAIN/1=AB/2=AB,:CLI,EMACS_SET_CLI_PREFIX");
  651.     do_system();
  652. #endif
  653.  
  654.     sleep(2);
  655.     return(TRUE);
  656. }
  657.  
  658. /*
  659.  * Run a one-liner in a subjob. When the command returns, wait for a single
  660.  * character to be typed, then mark the screen as garbage so a full repaint is
  661.  * done. Bound to "C-X !".
  662.  */
  663. int spawn(f, n)
  664. {
  665.     register int    s;
  666.     char            line[NLINE];
  667.  
  668.     /* don't allow this command if restricted */
  669.     if (restflag)
  670.         return(resterr());
  671.  
  672.     if ((s=mlreply("!", line, NLINE)) != TRUE)
  673.         return (s);
  674.     init_tline();
  675.     strcat(tline,line);
  676.     do_system();
  677.     do_system_end();
  678.     return (TRUE);
  679. }
  680.  
  681. /*
  682.  * Run an external program with arguments. When it returns, wait for a single
  683.  * character to be typed, then mark the screen as garbage so a full repaint is
  684.  * done. Bound to "C-X $".
  685.  */
  686.  
  687. int execprg(f, n)
  688.  
  689. {
  690.     register int    s;
  691.     char            line[NLINE];
  692.  
  693.     /* don't allow this command if restricted */
  694.     if (restflag)
  695.         return(resterr());
  696.  
  697.     if ((s=mlreply("!", line, NLINE)) != TRUE)
  698.         return (s);
  699.     strcpy(tline, line);
  700.     do_system();
  701.     do_system_end();
  702.     return (TRUE);
  703. }
  704.  
  705. /*
  706.  * Pipe a one line command into a window
  707.  * Bound to ^X @
  708.  *
  709.  * This command REQUIRES a directory named :TMP or a link by that name to 
  710.  * another directory such as :SL_TEMPS.  This diectory should have an
  711.  * ACL of  +,RWE  which will allow all users to access it.  This diectory is
  712.  * where the output file for this command is placed.  This was done because
  713.  * the sons of MircoEMACS do not always have the same privileges.  The file
  714.  * is of the pathname :TMP:pid.MICRO_EMACS_COMMAND where "pid" is the PID
  715.  * of the MicroEMACS process.  Also note that this sort of follows the UNIX(tm)
  716.  * convention for a common temporary file directory.
  717.  * The temp. file is created with an ACL of  username,OWAR
  718.  *
  719.  * See the THINGS_TO_DO.TXT for planned enhancements in this area.
  720.  *
  721.  */
  722. int pipecmd(f, n)
  723. {
  724.     register int    s;      /* return status from CLI */
  725.     register WINDOW *wp;    /* pointer to new window */
  726.     register BUFFER *bp;    /* pointer to buffer to zot */
  727.     char    line[NLINE];    /* command line send to shell */
  728.     const char pipecmd_bname[] = "command";
  729.     char pipecmd_filnam[NFILEN] = ":tmp:";  /* must be AOS/VS format!!!! */
  730.  
  731.  
  732.     /* don't allow this command if restricted */
  733.     if (restflag)
  734.         return(resterr());
  735.  
  736.     /* get the users pid and build a pathname for our scratch file */
  737.     ac0.ulng = 0L;
  738.     ac2.ulng = 0L;
  739.     ac1.ulng = -1L;
  740.     sys($PNAME, &ac0, &ac1, &ac2);    /* get our PID */
  741.     itoa(ac1.in, line);
  742.     strcat(pipecmd_filnam, line);     /* build temp. filename */
  743.     strcat(pipecmd_filnam, ".micro_emacs_command");
  744.  
  745.     zero((char *) &create_pkt, sizeof(create_pkt));
  746.     zero(acl_buf, $MXACL);
  747.     ac2.cptr = &acl_buf;
  748.     ac0.ulng = -1L;
  749.     ac1.ulng = -1L;
  750.     sys($GUNM, &ac0, &ac1, &ac2);     /* get our user name */
  751.     ac0.cptr = &acl_buf[strlen(acl_buf)];
  752.     ac0.cptr++;
  753.     *ac0.cptr = ($FACO | $FACW | $FACA | $FACR);  /* specify the ACL */
  754.     ac0.cptr++;
  755.     *ac0.cptr = '\000';
  756.     create_pkt.cacp = &acl_buf;         /* load addr of temp file ACL */
  757.  
  758.     create_pkt.ctim = -1L;
  759.     create_pkt.cdel = -1L;
  760.     create_pkt.cmil = -1L;
  761.     create_pkt.cftyp_format = $ORDS;    /* data sensitive */
  762.     create_pkt.cftyp_entry  = $FTXT;    /* TEXT file type */
  763.     ac2.ptr = &create_pkt;
  764.     ac1.lng = 0L;
  765.     ac0.cptr = &pipecmd_filnam;
  766.     sys($CREATE, &ac0, &ac1, &ac2);   /* have AOS/VS create the temp file */
  767.  
  768.     /* get the command to pipe in */
  769.     if ((s=mlreply("@", line, NLINE)) != TRUE)
  770.         return(s);
  771.  
  772.     /* get rid of the command output buffer if it exists */
  773.     if ((bp=bfind(pipecmd_bname, FALSE, 0)) != FALSE) {
  774.         /* try to make sure we are off screen */
  775.         wp = wheadp;
  776.         while (wp) {
  777.             if (wp->w_bufp == bp) {
  778.                 onlywind(FALSE, 1);
  779.                 break;
  780.             }
  781.             wp = wp->w_wndp;
  782.         }
  783.         if (zotbuf(bp) != TRUE)
  784.             return(FALSE);
  785.     }
  786.  
  787.     s = 0;                          /* init. index into line        */
  788.     init_tline();
  789.     strcat(tline,"LISTFILE,");      /* give CLI an @LIST to use     */
  790.     strcat(tline,pipecmd_filnam);           /* tack on the filename for @LIST */
  791.     strcat(tline,";");              /* separate the commands        */
  792.     s = strpbrk(line,",; \t");      /* check for cmd line delimiters */
  793.     if (s) {                        /* find any?    */
  794.         strncat(tline,line,(s-(int) &line));/* get whats before the delimeter*/
  795.         strcat(tline,"/L");         /* tack on "use @LIST file" switch */
  796.         strcat(tline,s);            /* get the rest of the cmd line */
  797.     } else {                        /* no delimiers...      */
  798.          strcat(tline,line);        /* get the cmd line     */
  799.         strcat(tline,"/L");         /* tack on "use @LIST file" switch*/
  800.     }
  801.     strcat(tline,";BYE/L=@NULL");   /* tell CLI to die quietly      */
  802.     do_system();
  803.     s = TRUE;
  804.  
  805.     /* split the current window to make room for the command output */
  806.     if (splitwind(FALSE, 1) == FALSE)
  807.         goto fubar;
  808.  
  809.     /* and read the stuff in */
  810.     if (getfile(pipecmd_filnam, FALSE) == FALSE)
  811.         goto fubar;
  812.  
  813.     /* make this window in VIEW mode, update all mode lines */
  814.     curwp->w_bufp->b_mode |= MDVIEW;
  815.     wp = wheadp;
  816.     while (wp) {
  817.         wp->w_flag |= WFMODE;
  818.         wp = wp->w_wndp;
  819.     }
  820.  
  821.     /* and get rid of the temporary file */
  822.     unlink(pipecmd_filnam);
  823.     return(TRUE);
  824.  
  825. fubar:
  826.     unlink(pipecmd_filnam);
  827.     return(FALSE);
  828. }
  829.  
  830. /*
  831.  * filter a buffer through an external DOS program
  832.  * Bound to ^X #
  833.  */
  834. int filter(f, n)
  835.  
  836. {
  837.     mlwrite(TEXT217);
  838. /*    mlwrite("[Not available yet under AOS/VS]");*/
  839.     sleep(1);
  840.     return(FALSE);
  841. }
  842.  
  843.  
  844. /*
  845.     return a system dependant string with the current time
  846.     original version didn't work.  modified idea of bill benedetto by
  847.     doug rady.  note the use of sys($ITIME, ...)  instead of sys_itime() 
  848. */
  849. char *PASCAL NEAR timeset()
  850.  
  851. {
  852.     register char *sp;      /* temp string pointer */
  853.     short int tvec[2];
  854.     extern char *dg_ctime();
  855.  
  856.     ac0.ulng = 0L;
  857.     ac1.ulng = 0L;
  858.     ac2.ulng = 0L;
  859.     sys($ITIME, &ac0, &ac1, &ac2);    /* get system time */
  860.     tvec[0] = ac2.in;
  861.     ac1.lng /= 32768L;
  862.     tvec[1] = (int)(ac1.lng/2L);
  863.     sp = dg_ctime(tvec);
  864.     sp[ strlen(sp)-1 ] = NULL;
  865.     return(sp);
  866. }
  867.  
  868. VOID init_tline()
  869. {
  870.     extern char *curdir();
  871.  
  872.     tline[0] = '\000';
  873.     strcat(tline, "DIR,");
  874.     curdir(&tline[4]);
  875.     strcat(tline, ";");
  876.     return;
  877. }
  878.  
  879. VOID do_system()
  880. {
  881.     movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  882.     mlerase();
  883.     TTclose();                              /* stty to old modes    */
  884.     system(tline);
  885.     TTkopen();
  886.     sgarbf = TRUE;
  887. }
  888.  
  889. VOID do_system_end()
  890. {
  891.     int s;
  892.  
  893.     if  (clexec == TRUE) {
  894.         mlputs(TEXT188);
  895. /*        mlputs("[End]");*/
  896.         TTflush();
  897.         while ((s = tgetc()) != '\r' && s != ' ')
  898.             ;
  899.     }
  900.     return;
  901. }
  902.  
  903. /*
  904.     Data General AOS/VS terminal handling routines
  905.   
  906.     Known types are:
  907.       DASHER D2xx/4xx series - support primarily for D2xx series
  908.       written by Doug Rady (based on ANSI.C and VMSVT.C)
  909.  */
  910. extern  VOID    ttopen();
  911. extern  VOID    ttkopen();
  912. extern  VOID    ttkclose();
  913. extern  VOID    tteeol();
  914. extern  VOID    tteeop();
  915. extern  VOID    ttbeep();
  916. extern  VOID    dashermove();
  917. extern  VOID    ansimove();
  918. extern  VOID    dasherrev();
  919. extern  VOID    ansirev();
  920. extern  int     ttcres();
  921. #if     COLOR
  922. extern  VOID    ttfcol();
  923. extern  VOID    ttbcol();
  924. #endif
  925. extern  VOID    dasherdim();
  926. extern  VOID    ansidim();
  927. extern  VOID    spal();
  928.  
  929. #define NROWS   24              /* normal # of screen rows */
  930. #define MXROWS  24              /* max # of screen rows */
  931. #define NCOLS   80              /* normal mode # of screen columns*/
  932. #define MXCOLS  135             /* wide mode # of screen columns*/
  933. #define MARGIN  4               /* size of minimim margin and   */
  934. #define SCRSIZ  64              /* scroll size for extended lines */
  935. #define NPAUSE  100             /* # times thru update to pause */
  936. #define ESC     0x16
  937. #define BEL     7
  938.  
  939. /*
  940.  * Dispatch table. All the
  941.  * hard fields just point into the
  942.  * terminal I/O code.
  943.  */
  944. noshare TERM    term    = {
  945.         MXROWS -1,
  946.         NROWS -1,
  947.         MXCOLS,
  948.         NCOLS,
  949.     0, 0,
  950.         MARGIN,
  951.         SCRSIZ,
  952.         NPAUSE,
  953.         &ttopen,
  954.         &ttclose,
  955.         &ttkopen,
  956.         &ttkclose,
  957.         &ttgetc,
  958. #if TTPUTC == 0
  959.         &ttputc,
  960. #endif
  961. #if TTFLUSH == 0
  962.         &ttflush,
  963. #endif
  964.         &dashermove,
  965.         &tteeol,
  966.         &tteeop,
  967.         &tteeop,
  968.         &ttbeep,
  969.         &dasherrev,
  970.         &ttcres,
  971.         &dasherdim,
  972. #if     COLOR
  973.         &ttfcol,
  974.         &ttbcol
  975. #endif
  976. };
  977.  
  978. /*
  979.     dashermove - Move the cursor for DG Dasher
  980.  */
  981. VOID dashermove(row, col)
  982. {
  983.     TTputc('\020');
  984.     TTputc(col);
  985.     TTputc(row);
  986. }
  987.  
  988. /*
  989.     ansimove - Move the cursor for ANSI crt
  990.  */
  991. VOID ansimove(row, col)
  992.  
  993. int row, col;
  994. {
  995.     char rc_tmp[ 8 ];
  996.  
  997.     ++row;
  998.     ++col;
  999.     ttputs("\033[");
  1000.     itoa(row, rc_tmp);
  1001.     ttputs(rc_tmp);
  1002.     TTputc(';');
  1003.     itoa(col, rc_tmp);
  1004.     ttputs(rc_tmp);
  1005.     TTputc('H');
  1006. }
  1007.  
  1008. /*
  1009.  *  dasherrev - set the reverse video status for DG Dasher
  1010.  */
  1011. VOID dasherrev(status)
  1012.  
  1013. int status;     /* TRUE = reverse video, FALSE = normal video */
  1014. {
  1015.     if (status)
  1016.         ttputs("\036\104");
  1017.     else
  1018.         ttputs("\036\105");
  1019. }
  1020.  
  1021. /*
  1022.  *  ansirev- set the reverse video status for ANSI crt
  1023.  */
  1024. VOID ansirev(status)
  1025.  
  1026. int status;
  1027. {
  1028.     if  (dimsts) {
  1029.         if (status) {
  1030.             ttputs("\033[0;2;7m");
  1031.         } else {
  1032.             ttputs("\033[0;2m");
  1033.         }
  1034.     } else {
  1035.         if (status) {
  1036.             ttputs("\033[0;7m");
  1037.         } else {
  1038.             ttputs("\033[0m");
  1039.         }
  1040.     }
  1041.     if  (status)
  1042.         revsts = TRUE;
  1043.     else
  1044.         revsts = FALSE;
  1045. }
  1046.  
  1047. /*
  1048.  *  dasherdim - set the dim/bright video status for DG Dasher
  1049.  */
  1050. VOID dasherdim(status)
  1051.  
  1052. int status;     /* TRUE = dim video, FALSE = bright video */
  1053. {
  1054.     if (status)
  1055.        TTputc('\034');
  1056.     else
  1057.        TTputc('\035');
  1058. }
  1059.  
  1060. /*
  1061.  *  ansidim - set the dim/bright video status for ANSI crt
  1062.  */
  1063. VOID ansidim(status)
  1064.  
  1065. int status;
  1066. {
  1067.     if  (revsts) {
  1068.         if (status) {
  1069.             ttputs("\033[0;2;7m");
  1070.         } else {
  1071.             ttputs("\033[0;7m");
  1072.         }
  1073.     } else {
  1074.         if (status) {
  1075.             ttputs("\033[0;2m");
  1076.         }
  1077.         else
  1078.         {
  1079.             ttputs("\033[0m");
  1080.         }
  1081.     }
  1082.     if  (status)
  1083.         dimsts = TRUE;
  1084.     else
  1085.         dimsts = FALSE;
  1086. }
  1087.  
  1088. /*
  1089.     ttcres - Change screen resolution (what resolution?)
  1090. */
  1091. int ttcres()
  1092. {
  1093.         return(TRUE);
  1094. }
  1095.  
  1096. VOID spal()          /* change palette string */
  1097.  
  1098. {
  1099.         /*      Does nothing here       */
  1100. }
  1101.  
  1102. #if     COLOR
  1103. /*
  1104.     ttfcol - Set the forground color (not implimented)
  1105.  */
  1106. VOID ttfcol()
  1107. {
  1108. }
  1109.  
  1110. /*
  1111.     ttbcol - Set the background color (not implimented)
  1112.  */
  1113.  
  1114. VOID ttbcol()
  1115. {
  1116. }
  1117. #endif  /* COLOR */
  1118.  
  1119. /*
  1120.     tteeol - Erase to end of line
  1121.  */
  1122. VOID tteeol()
  1123. {
  1124.     ttputs(crt_eol);
  1125. }
  1126.  
  1127.  
  1128. /*
  1129.     tteeop - Erase to end of page (clear screen)
  1130.  */
  1131. VOID tteeop()
  1132. {
  1133.     ttputs(crt_eop);
  1134. }
  1135.  
  1136.  
  1137. /*
  1138.     ttbeep - Ring the bell
  1139.  */
  1140. VOID ttbeep()
  1141. {
  1142.     TTputc('\007');
  1143. }
  1144.  
  1145. VOID ttputs(str)
  1146. char *str;
  1147. {
  1148.     while(*str) {
  1149.         putc(*str, stdout);
  1150.     str++;
  1151.     }
  1152. }
  1153.  
  1154. /*
  1155.     ttopen() - open the terminal and change characteristics for our use
  1156.  */
  1157.  
  1158. VOID ttopen()
  1159. {
  1160.     int sys_err;
  1161.     P_CHAR_EX   crt_info;               /* for ?GECHR system call */
  1162.     /*
  1163.     set some traps
  1164.     */
  1165.     signal(SIGTRAP, &traceback);
  1166.     signal(SIGIOT,  &traceback);
  1167.     signal(SIGILL,  &traceback);
  1168.     signal(SIGSEGV, &traceback);
  1169.     signal(SIGTERM, &traceback);
  1170. /*    signal(SIGINT,  &traceback);*/
  1171.     signal(SIGQUIT, &traceback);
  1172.     signal(SIGEMT,  &traceback);
  1173.     signal(SIGFPE,  &traceback);
  1174.     signal(SIGKILL, &traceback);
  1175.     signal(SIGBUS,  &traceback);
  1176.     signal(SIGSYS,  &traceback);
  1177.     signal(SIGTERM, &traceback);
  1178.  
  1179.     strcpy(os, "AOS");        /* tell us what OS we run */
  1180.     ac0.in = fchannel(stdout);    /* make sure it is opened */
  1181.     ac0.in = fchannel(stdin);     /* make sure it is opened */
  1182.     ac1.ulng = (BIT0 | (sizeof(crt_info)/2)); /* get characteristics flag */
  1183.     ac2.ptr = (unsigned long*) &crt_info;
  1184.  
  1185.     sys_err = sys($GECHR, &ac0, &ac1, &ac2);    /* ?GECHR system call */
  1186.  
  1187.     /*
  1188.         copy the actual stdio pointer macro values into pointers
  1189.     */
  1190.     STDIN   = stdin;
  1191.     STDOUT  = stdout;
  1192.  
  1193.     /*
  1194.         set LPP & CPL in case they aren't == defaults - idea from bill benedetto
  1195.         resetting the max. row value is condtional because some of us can
  1196.         display more than LPP lines on a screen.
  1197.     */
  1198.     term.t_ncol = (short)crt_info.char_cpl;     /* get CPL */
  1199.     term.t_nrow = ((short)crt_info.char_lpp -1);/* get LPP */
  1200.     if  (term.t_nrow > term.t_mrow)   /* only reset max. row if LPP is > */
  1201.         term.t_mrow = term.t_nrow;      /* default max. row */
  1202.  
  1203. #if XXCRT
  1204.     if  (termcode == 0) { /* CRT type given on command line? */
  1205.         /* nope, we must figure it out */
  1206.     }
  1207.     
  1208.     switch  (termcode) {
  1209.         case 0: /* Generic ANSI compliant */
  1210.             strcpy(sres, "ANSI");
  1211.             crt_eol     = "\033[K";
  1212.             crt_eop     = "\033[J";
  1213.             term.t_move = &ansimove;
  1214.             term.t_rev  = &ansirev;
  1215.             term.t_dim  = &ansidim;
  1216. /*
  1217.             term.t_getkey = &ansigetkey;
  1218. */
  1219.             break;
  1220.         case 1: /* DEC VT100 */
  1221.         case 2: /* DEC VT100K */
  1222.             strcpy(sres, "VT100");
  1223.             crt_eol     = "\033[K";
  1224.             crt_eop     = "\033[J";
  1225.             term.t_move = &ansimove;
  1226.             term.t_rev  = &ansirev;
  1227.             term.t_dim  = &ansidim;
  1228. /*
  1229.             term.t_getkey = &vt100getkey;
  1230. */
  1231.             break;
  1232.         case 4: /* DEC VT102 */
  1233.         case 5: /* DEC VT102K */
  1234.             strcpy(sres, "VT102");
  1235.             crt_eol     = "\033[K";
  1236.             crt_eop     = "\033[J";
  1237.             term.t_move = &ansimove;
  1238.             term.t_rev  = &ansirev;
  1239.             term.t_dim  = &ansidim;
  1240.             crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE);
  1241. /*
  1242.             term.t_getkey = &vt100getkey;
  1243. */
  1244.             break;
  1245.         case 7: /* DEC VT220 */
  1246.         case 8: /* DEC VT220K */
  1247.             strcpy(sres, "VT220");
  1248.             crt_eol     = "\033[K";
  1249.             crt_eop     = "\033[J";
  1250.             term.t_move = &ansimove;
  1251.             term.t_rev  = &ansirev;
  1252.             term.t_dim  = &ansidim;
  1253. /*
  1254.             term.t_getkey = &vt220getkey;
  1255. */
  1256.             break;
  1257.         case 6: /* D.G. Dasher D4xx */
  1258.             strcpy(sres, "DGD400");
  1259.             crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE);
  1260.             break;
  1261.         case 3: /* D.G. Dasher D2xx */
  1262.         default;
  1263.             strcpy(sres, "DGD200");
  1264.     }
  1265. #else
  1266.     if  ((crt_info.char_cdt != char_d2xx)    /* is not CRT3 or D2xx ?  and */
  1267.     &&  (crt_info.char_cdt != char_d4xx)) {  /* is not CRT6 or D4xx or D5xx ? */
  1268.         crt_eol     = "\033[K";
  1269.         crt_eop     = "\033[J";
  1270.         term.t_move = &ansimove;
  1271.         term.t_rev  = &ansirev;
  1272.         term.t_dim  = &ansidim;
  1273.         strcpy(sres, "ANSI");
  1274.     }
  1275. #endif  /* XXCRT */
  1276.  
  1277.     /*
  1278.         change terminal charactersitcs to Unix(tm) raw mode
  1279.     */
  1280.     ioctl(STDIN->_file, TCGETA, &old_in_termio);    /* save old settings */
  1281.     new_in_termio.c_iflag = 0;            /* setup new settings */
  1282.     new_in_termio.c_oflag = 0;
  1283.     new_in_termio.c_lflag = 0;
  1284.     new_in_termio.c_cc[VTIME] = 0;
  1285.     new_in_termio.c_cc[VMIN] = 1;
  1286.     new_in_termio.c_line = BELL_LD;       /* emulate unix(tm) line handling */
  1287.     new_in_termio.c_cflag = old_in_termio.c_cflag;
  1288.     ioctl(STDIN->_file, TCSETA, &new_in_termio);
  1289.     kbdflgs = fcntl(STDIN->_file, F_GETFL, 0);
  1290.     dimsts = 0;
  1291.     revsts = 0;
  1292.  
  1293.     /*
  1294.     check for mouse here
  1295.     */
  1296.     mexist = 0;
  1297.     nbuttons = 0;
  1298.     oldbut = 0;
  1299.  
  1300.     /*
  1301.         on all screens we are not sure of the initial position
  1302.         of the cursor
  1303.     */
  1304.     ttrow = 999;
  1305.     ttcol = 999;
  1306.  
  1307.     /* assume terminal has following */
  1308.     eolexist = TRUE;
  1309.     revexist = TRUE;
  1310.     strcpy(sres, "NORMAL");
  1311.  
  1312.     /*
  1313.         here we lower the priority of this task so that the console
  1314.     reader task will always get control when we get a char.
  1315.     */
  1316.     ac0.ulng = 0L;                      /* will get TID of this task */
  1317.     ac1.ulng = 0L;                      /* will get task pri. this task */
  1318.     ac2.ulng = 0L;                      /* who knows... */
  1319.     sys($MYTID, &ac0, &ac1, &ac2);
  1320.     ac1.ulng = 100L;                    /* new task priority */
  1321.     ac2.ulng = 0L;                      /* must be zero... */
  1322.     sys($IDPRI, &ac1, &ac0, &ac2);      /* do it!!! */
  1323.  
  1324. }
  1325.  
  1326. /*
  1327.     open the keyboard
  1328. */  
  1329. VOID ttkopen()
  1330. {
  1331.     /*
  1332.         activate the MircoEmacs console characteristics
  1333.     */
  1334.     ioctl(STDIN->_file, TCSETA, &new_in_termio);
  1335.     fcntl(STDIN->_file, F_SETFL, kbdflgs);
  1336.     kbdqp = 0;
  1337.     kbdpoll = FALSE;
  1338.     kbdq = '\000';
  1339.     in_init();
  1340. }
  1341.  
  1342. VOID ttkclose()
  1343. {
  1344. }
  1345.  
  1346. #if     FLABEL
  1347. fnclabel(f, n)          /* label a function key */
  1348.  
  1349. int f,n;        /* default flag, numeric argument [unused] */
  1350.  
  1351. {
  1352.         /* on machines with no function keys...don't bother */
  1353.         return(TRUE);
  1354. }
  1355. #endif
  1356.  
  1357. /*
  1358.      Change the current working directory
  1359. */
  1360. PASCAL NEAR int chdirectory()
  1361.  
  1362. {
  1363. #if CHDIR                               /* include this code?   */
  1364.  
  1365.     /* don't allow this command if restricted    */
  1366.     if (restflag)
  1367.         return(resterr());
  1368.  
  1369.     if ((ac0.in = mlreply("Directory: ", tline, NLINE)) != TRUE)
  1370.         return(ac0.in);
  1371.     
  1372.     ac0.in = chdir(tline);    /* change the current working directory */
  1373.  
  1374.     /*
  1375.     tell the story... success or failure
  1376.     */
  1377.     if (ac0.in) {
  1378.         mlwrite("Error- directory not changed.");
  1379.         return(ac0.in);
  1380.     }
  1381.     else {
  1382.         mlwrite("Directory changed.");
  1383.     return(TRUE);
  1384.     }
  1385. #endif
  1386. }
  1387.  
  1388.  
  1389. #if ORMDNI
  1390.  
  1391. /*
  1392.     superuser on/off toggle routines to override those annoying ACLs
  1393.  
  1394.     usage:  superuser_on();  or  superuser_off();
  1395.  
  1396. */
  1397. int superuser_on()
  1398.  
  1399. {
  1400.     int err;
  1401.  
  1402.     if  (restflag)
  1403.         return(resterr());
  1404.  
  1405.     ac0.lng = -1L;
  1406.     ac1.ulng = 0L;
  1407.     ac2.ulng = 0L;
  1408.     err = 0;
  1409.  
  1410.     if  ((err = sys($SUSER, &ac0, &ac1, &ac2)))
  1411.         if  (err = ERPRV)
  1412.         mlwrite("Error: you are not allowed use of superuser.");
  1413.         else
  1414.         mlwrite("Error turning superuser ON.");
  1415.  
  1416.     return(err);
  1417. }
  1418.  
  1419.  
  1420. int superuser_off()
  1421.  
  1422. {
  1423.     int err;
  1424.  
  1425.     if  (restflag)
  1426.         return(resterr());
  1427.  
  1428.     ac0.ulng = 1L;
  1429.     ac1.ulng = 0L;
  1430.     ac2.ulng = 0L;
  1431.     err = 0;
  1432.  
  1433.     if  ((err = sys($SUSER, &ac0, &ac1, &ac2)))
  1434.         mlwrite("Error turning superuser OFF.");
  1435.  
  1436.     return(err);
  1437. }
  1438. #endif
  1439.  
  1440. #if     ISADIR
  1441. int isadirectory(fstream)
  1442.  
  1443. FILE *fstream;
  1444.  
  1445. {
  1446.     return(isadir(fstream->_file));
  1447. }
  1448. #endif
  1449.  
  1450.  
  1451. /****************************************************************************/
  1452. /*                                                                          */
  1453. /*                                                                          */
  1454. /*  All aosvs$ library routines Copyright (c) 1989 by Douglas C. Rady       */
  1455. /*                                                                          */
  1456. /*                                                                          */
  1457. /****************************************************************************/
  1458.  
  1459. /*
  1460.     aosvs$bsd_dir.h -- a replacement inlcude file under AOS/VS for:
  1461.     <dir.h> -- definitions for 4.2BSD-compatible directory access
  1462.  
  1463.         Taken from GNU's emacs/etc/ndir.h for porting GNU stuff to AOS/VS.
  1464.  
  1465.         All of the usual fields are defined but dd_buf is defined as a char*
  1466.     so we can pass a poniter to a template under AOS/VS.
  1467. */
  1468.  
  1469. #ifndef DIRSIZ
  1470. struct direct {                /* data from readdir() */
  1471.     long        d_ino;        /* inode number of entry */
  1472.     unsigned short    d_reclen;    /* length of this record */
  1473.     unsigned short    d_namlen;    /* length of string in d_name */
  1474.     char        d_name[$MXFN];    /* name of file */
  1475.     };
  1476. #endif
  1477.  
  1478. typedef struct {
  1479.     int    dd_fd;            /* file desc. - channel# under aos/vs */
  1480.     int    dd_loc;            /* offset in block */
  1481.     int    dd_size;        /* amount of valid data */
  1482.         char   *dd_buf;                 /* pointer to wildcard/template */
  1483.     }    DIR;                    /* stream data from opendir() */
  1484.  
  1485. /*
  1486.     set up the MV/Eclipse accumulators used by the  aosvs$  routines
  1487. */
  1488. $align(1) $low32k union aosvs$accumulator { /* dearly beloved, we are gathered here...*/
  1489.     unsigned long * ptr;            /* pointer to unsigned long */
  1490.     char *          cptr;           /* pointer to char */
  1491.     unsigned int  * pint;           /* pointer to unsigned int */
  1492.     unsigned short *psht;           /* pointer to short */
  1493.     unsigned long   ulng;           /* unsigned long */
  1494.     signed long     lng;            /* signed long */
  1495.     unsigned int    uin;            /* unsigned int */
  1496.     signed int      in;             /* signed int */
  1497.     unsigned short usht;            /* unsigned short */
  1498.     unsigned char   chr;            /* a char, unsigned of course!!! */
  1499. } aosvs$ac0, aosvs$ac1, aosvs$ac2;  /* our bountiful accumulators, sigh... */
  1500.  
  1501.  
  1502. /*
  1503.     aosvs$bsd_dir.c -- fake 4.2BSD directory access routines for AOS/VS
  1504.  
  1505.     System call city...
  1506.  
  1507. */
  1508.  
  1509. P_GNFN aosvs$bsd_gnfn_pkt;
  1510.  
  1511. /*
  1512.     aosvs$bsd_closedir
  1513. */
  1514. void closedir(dir_stream)  /* $name("aosvs$bsd_closedir") */
  1515.  
  1516. DIR *dir_stream;
  1517.  
  1518. {
  1519.     aosvs$ac0.ulng = 0L;
  1520.     aosvs$ac2.ulng = 0L;
  1521.     aosvs$ac1.in = dir_stream->dd_fd;   /* load channel number */
  1522.     sys($GCLOSE, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2);
  1523. }
  1524.  
  1525.  
  1526. /*
  1527.     aosvs$bsd_opendir
  1528. */
  1529.  
  1530. DIR *opendir(dir_name) /* name$("aosvs$bsd_opendir") */
  1531.  
  1532. char *dir_name;
  1533.  
  1534. {
  1535.  
  1536. #include    "packets/block_io.h"
  1537.     
  1538.     P_GOPEN gopen_pkt;
  1539.     DIR *dir_stream;
  1540.     int err;
  1541.     char t_name[$MXPL];
  1542.  
  1543.     err = 0;
  1544.     dir_stream = (DIR *) malloc(sizeof(DIR));
  1545.     zero((char *) dir_stream, sizeof(DIR));
  1546.     zero((char *) &aosvs$bsd_gnfn_pkt, sizeof(aosvs$bsd_gnfn_pkt));
  1547.     zero((char *) &gopen_pkt, sizeof(gopen_pkt));
  1548.  
  1549.     err = aosvs$expand_pathname(dir_name, t_name);
  1550.     aosvs$ac0.cptr = t_name;
  1551.     aosvs$ac1.lng = -1L;
  1552.     aosvs$ac2.ptr = &gopen_pkt;
  1553.  
  1554.     /* Try to ?GOPEN the file. */
  1555.     if (err = sys($GOPEN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2)) {
  1556.         free(dir_stream);       /* Error Will Robinson! Error! Error! */
  1557.         return(NULL);
  1558.     }
  1559.  
  1560.     /* Make sure it is some type of directory! */
  1561.     if ((gopen_pkt.opty_type != $FDIR) && (gopen_pkt.opty_type != $FLDU)
  1562.     && (gopen_pkt.opty_type != $FCPD)) {    /* AOS/VS 7.62 directory types. */
  1563.         dir_stream->dd_fd = (int)gopen_pkt.opch;
  1564.         closedir(dir_stream);
  1565.         free(dir_stream);       /* Error Will Robinson! Error! Error! */
  1566.         return(NULL);
  1567.     }
  1568.  
  1569.     dir_stream->dd_fd = (int)gopen_pkt.opch;    /* stash the channel number */
  1570.     return(dir_stream);
  1571. }
  1572.  
  1573.  
  1574. /*
  1575.     aosvs$bsd_readdir
  1576. */
  1577.  
  1578. struct direct *readdir(dir_stream)   /* name$("aosvs$bsd_readdir") */
  1579.  
  1580. DIR *dir_stream;
  1581.  
  1582. {
  1583.     struct direct *dptr;
  1584.  
  1585.     dptr = NULL;
  1586.     aosvs$ac0.in = 0;
  1587.     aosvs$ac1.in = dir_stream->dd_fd;   /* load channel number */
  1588.  
  1589.     dptr = (struct direct *) malloc(sizeof(struct direct));
  1590.     zero((char *)dptr, sizeof(struct direct));
  1591.  
  1592.     if (dir_stream->dd_loc)
  1593.         aosvs$bsd_gnfn_pkt.nfky     = (short)dir_stream->dd_loc;
  1594.     else
  1595.         aosvs$bsd_gnfn_pkt.nfky     = 0;
  1596.  
  1597.     if (dir_stream->dd_buf)         /* if passed a template */
  1598.         aosvs$bsd_gnfn_pkt.nftp = dir_stream->dd_buf;   /* load it into packet */
  1599.     else
  1600.         aosvs$bsd_gnfn_pkt.nftp   = (char *) -1L;   /* load default flag */
  1601.  
  1602.     aosvs$bsd_gnfn_pkt.nfnm   = dptr->d_name;       /* load buffer ptr */
  1603.     aosvs$ac2.ptr  = &aosvs$bsd_gnfn_pkt;
  1604.     if  (sys($GNFN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2) == 0)
  1605.     {
  1606.         /* save the AOS/VS internal pointer */
  1607.         dir_stream->dd_loc = (int) aosvs$bsd_gnfn_pkt.nfky;
  1608.  
  1609.         /* load the direct struct values */
  1610.         dptr->d_ino = (long) aosvs$bsd_gnfn_pkt.nfky;   /* fake an inode */
  1611.         dptr->d_reclen = sizeof(struct direct);         /* why? why not? */
  1612.     dptr->d_namlen = strlen(dptr->d_name);          /* handy to have */
  1613.     return(dptr);
  1614.     }
  1615.  
  1616.     free(dptr);
  1617.     return(NULL);    
  1618. }
  1619.  
  1620.  
  1621. /*
  1622.     aosvs$bsd_seekdir
  1623. */
  1624.  
  1625. void seekdir(dir_stream, pos)  /* name$("aosvs$bsd_seekdir") */
  1626.  
  1627. DIR *dir_stream;
  1628. long pos;
  1629.  
  1630. {
  1631.     dir_stream->dd_loc = (short)pos;
  1632. }
  1633.  
  1634.  
  1635. /*
  1636.     aosvs$bsd_telldir
  1637. */
  1638.  
  1639. long telldir(dir_stream)  /* name$("aosvs$bsd_telldir") */
  1640.  
  1641. DIR *dir_stream;
  1642.  
  1643. {
  1644.     return(dir_stream->dd_loc);
  1645. }
  1646.  
  1647.  
  1648. /*
  1649. aosvs$unix_to_aosvs_path.c -- convert a Unix(tm) pathname to a Aos/Vs pathname
  1650.                               We also accept the Ms-Dos '\' seperator and
  1651.                   convert it to the Unix(tm) '/' seperator.  We do
  1652.                   not deal with Ms-Dos device specifiers. The '\'
  1653.                   is handled since most current Ms-Dos C compilers
  1654.                   can deal with either '\' or '/'.
  1655.  
  1656. usage:
  1657.     aosvs$unix_to_aosvs(u_path, a_path);
  1658.  
  1659. where:
  1660. data item name          data type           description
  1661. ----------------------- ------------------  -----------------------------------
  1662. u_path                  char *              char * of Unix(tm) pathname,
  1663.                                             end with null.
  1664. a_path                  char *              char * for Aos/Vs pathname, MUST be
  1665.                                             $MXPL in length.
  1666.  
  1667. -------------------------------------------------------------------------------
  1668. edit history
  1669.  
  1670. who  mm/dd/yy  rev #  what.....................................................
  1671. ---  --------  -----  ---------------------------------------------------------
  1672. dcr  01/27/89  01.00  birth, new life, creation...
  1673. dcr  03/02/89  01.01  cleaned up, added internal temp. storage for path.
  1674. dcr  03/02/89  01.02  added code to deal with Ms-Dog '\' seperator.
  1675. dcr  03/02/89  01.03  added code to skip out if first char is legal Aos/Vs char.
  1676.                       This makes us "just like" _toaos_fid().
  1677. */
  1678. void aosvs$unix_to_aosvs_path(u_path, a_path)
  1679.  
  1680. char *u_path, *a_path;
  1681. {
  1682.  
  1683.     extern int _toaos_fid();        /* Data General library routine */
  1684.  
  1685.     /*
  1686.     local variables
  1687.     */
  1688.     register char *up, *ap;
  1689.     register int dec1;
  1690.     char t_path[$MXPL], octal[4];
  1691.  
  1692.     /*
  1693.     check for null ptrs... no tricks here please...
  1694.     */
  1695.     if ((u_path == NULL) || (a_path == NULL))
  1696.         return;
  1697.  
  1698.     /*
  1699.     copy to register vars.
  1700.     */
  1701.     up = u_path;            /* load ptr to Unix(tm) path */
  1702.     ap = t_path;            /* load ptr to temp. storage area */
  1703.     zero(t_path, $MXPL);    /* zero the temp. storage area */
  1704.             
  1705.     /*
  1706.     to be "just like" DG's _toaos_fid()  we skip out if the first char. is a
  1707.     legal Aos/Vs seperator.  This is from page 2-1 of the "Using Specialized
  1708.     C Functions" manual, DG part number 093-000585-00.
  1709.     */
  1710.     if ((*up == '^') || (*up == '@') || (*up == '=') || (*up == ':')) {
  1711.         strcpy(a_path, u_path);
  1712.     return;
  1713.     }
  1714.  
  1715.     /*
  1716.     step through the unix(tm) pathname and copy or translate bytes into
  1717.     the temp. storage area.
  1718.     */
  1719.     while (*up) {     /* better be NULL terminated!!! */
  1720.         if ((*up == '$') || (*up == '?') || (*up == '\\') || (*up == '_')
  1721.     || ((*up >= '.') && (*up <= ':'))   /* thank you ASCII */
  1722.     || ((*up >= 'A') && (*up <= 'Z'))
  1723.     || ((*up >= 'a') && (*up <= 'z'))) {
  1724.             if (*up == '\\') {   /* convert ms-dos '\' to unix(tm) '/' */
  1725.             *ap++ = '/';
  1726.         up++;
  1727.                 continue;
  1728.             }
  1729.         *ap++ = *up++;
  1730.             continue;
  1731.         }
  1732.  
  1733.         dec1 = 0;
  1734.         zero(octal, 4);
  1735.         *ap++ = '?';            /* marker for octal replacement */
  1736.         dec1 = (int)*up;
  1737.         otoa(dec1, octal);
  1738.         if (dec1 < 64)
  1739.         *ap++ = '0';
  1740.         strcat(ap, octal);
  1741.         if (dec1 >= 64)
  1742.         ap++;
  1743.         ap++;
  1744.     ap++;
  1745.         up++;
  1746.     }
  1747.  
  1748.     *ap = NULL;
  1749.  
  1750.     /*
  1751.     go home...
  1752.     */
  1753.     _toaos_fid(t_path, a_path);
  1754.  
  1755.     return;
  1756. }
  1757.  
  1758. /*
  1759. aosvs$expand_pathname.c
  1760.  
  1761. usage:
  1762.     err = aosvs$expand_pathname(c_path, x_path);
  1763.  
  1764. where:
  1765. data item name          data type           description
  1766. ----------------------- ------------------  -----------------------------------
  1767. err                     int                 Error return, if any.
  1768. c_path                  char *              Current pathname.
  1769. x_path                  char *              Expanded pathname returned here.
  1770.                                             This must be at least $MXPL bytes.
  1771.  
  1772. -------------------------------------------------------------------------------
  1773. edit history
  1774.  
  1775. who  mm/dd/yy  rev #  what.....................................................
  1776. ---  --------  -----  ---------------------------------------------------------
  1777. dcr  03/02/89  01.00  birth, new life, creation...
  1778.  
  1779. */
  1780.  
  1781. /*
  1782. aosvs$expand_pathname.c
  1783.  
  1784. usage:
  1785.     err = aosvs$expand_pathname(c_path, x_path);
  1786.  
  1787. where:
  1788. data item name          data type           description
  1789. ----------------------- ------------------  -----------------------------------
  1790. err                     int                 Error return, if any.
  1791. c_path                  char *              Current pathname.
  1792. x_path                  char *              Expanded pathname returned here.
  1793.                                             This must be at least $MXPL bytes.
  1794.  
  1795. -------------------------------------------------------------------------------
  1796. edit history
  1797.  
  1798. who  mm/dd/yy  rev #  what.....................................................
  1799. ---  --------  -----  ---------------------------------------------------------
  1800. dcr  03/02/89  01.00  birth, new life, creation...
  1801.  
  1802. */
  1803.  
  1804. int aosvs$expand_pathname(c_path, x_path)
  1805.  
  1806. char *c_path, *x_path;
  1807.  
  1808. {
  1809.     /*
  1810.     local variables
  1811.     */
  1812.     char t_path[$MXPL];
  1813.  
  1814.     /*
  1815.     things to do...
  1816.     */
  1817.     zero(t_path, $MXPL);
  1818.     aosvs$unix_to_aosvs_path(c_path, t_path);
  1819.  
  1820.     aosvs$ac2.in = $MXPL;
  1821.     aosvs$ac0.cptr = t_path;
  1822.     aosvs$ac1.cptr = x_path;
  1823.     if (sys($GRNAME, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2))
  1824.         if ((aosvs$ac0.in == ERFDE) || (aosvs$ac0.in == ERFDE))
  1825.             strcpy(x_path, t_path);
  1826.         else
  1827.         return(1);
  1828.  
  1829.     return(0);
  1830. }
  1831.  
  1832. extern DIR        *opendir();
  1833. extern struct direct    *readdir();
  1834. extern long        telldir();
  1835. extern void        seekdir();
  1836. extern void        closedir();
  1837.  
  1838. #define rewinddir( dirp )    seekdir( dirp, 0L )
  1839.  
  1840.  
  1841. /*    FILE Directory routines        */
  1842.  
  1843. char gnfntmp[NFILEN];   /* wildcard template */
  1844. char gnfnpath[NFILEN];    /* path of file to find */
  1845. char gnfnrbuf[NFILEN];    /* return file buffer */
  1846. DIR *gnfndir;
  1847. struct direct *gnfndirect;
  1848.  
  1849. char PASCAL NEAR *getnfile();
  1850.  
  1851. /*  do a template directory search (for file name completion) */
  1852.  
  1853. char *PASCAL NEAR getffile(fspec)
  1854.  
  1855. char *fspec;    /* pattern to match */
  1856.  
  1857. {
  1858.     register int index;        /* index into various strings */
  1859.  
  1860.         /* clean up from our last time in here... */
  1861.         if (gnfndir) {
  1862.         closedir(gnfndir);
  1863.         free(gnfndir);
  1864.         }
  1865.  
  1866.         if (gnfndirect)
  1867.             free(gnfndirect);
  1868.  
  1869.         /* init. some things... */
  1870.         zero(gnfnpath, NFILEN);
  1871.         zero(gnfnrbuf, NFILEN);
  1872.     zero(gnfntmp, NFILEN);
  1873.         gnfndir = NULL;
  1874.         gnfndirect = NULL;
  1875.  
  1876.         /* first parse the file path off the file spec */
  1877.     strcpy(gnfnpath, fspec);
  1878.     index = strlen(gnfnpath) - 1;
  1879.     while (index >= 0 && (gnfnpath[index] != '/' &&
  1880.                 gnfnpath[index] != '\\' && gnfnpath[index] != ':'))
  1881.         --index;
  1882.  
  1883.     gnfnpath[index+1] = 0;
  1884.  
  1885.         if  ((gnfndir = opendir(gnfnpath)) == NULL)
  1886.         return(NULL);
  1887.  
  1888.         /* build the wildcard or template to use in the lookup */
  1889.         strcpy(gnfntmp, &fspec[index+1]);
  1890.         strcat(gnfntmp, "+");
  1891.         gnfndir->dd_buf = gnfntmp;
  1892.  
  1893.         return(getnfile());
  1894. }
  1895.  
  1896. char *PASCAL NEAR getnfile()
  1897.  
  1898. {
  1899.     register int index;        /* index into various strings */
  1900.  
  1901.         zero(gnfnrbuf, NFILEN);         /* init return buffer */
  1902.  
  1903.     /* and call for the next file */
  1904.         if ((gnfndirect = readdir(gnfndir)) == NULL) {
  1905.         closedir(gnfndir);
  1906.             free(gnfndir);
  1907.             gnfndir = NULL;
  1908.             return(NULL);
  1909.         }
  1910.  
  1911.     /* return the next file name! */
  1912.     strcpy(gnfnrbuf, gnfnpath);
  1913.         strcat(gnfnrbuf, gnfndirect->d_name);
  1914.     mklower(gnfnrbuf);
  1915.         free(gnfndirect);
  1916.         gnfndirect = NULL;
  1917.     return(gnfnrbuf);
  1918. }
  1919.  
  1920. FILE *xxfopen(fn, mode)     /* expand a pathname and open it */
  1921.  
  1922. char *fn, *mode;
  1923.  
  1924. {
  1925.     char tmppath[NFILEN];               /* temp. to hold expanded pathname */
  1926.  
  1927.     strcpy(tmppath, fn);                        /* load passed pathname */
  1928.     resolve_full_pathname(tmppath, tmppath);    /* expand it... */
  1929.     return(fopen(tmppath, mode));           /* try to open expanded pathname */
  1930. }
  1931.  
  1932. #endif  /* AOSVS */
  1933.